module UartReceiver(
  iRstN,
  iRx,
  iClk,
  iMode,
  oBusy,
  oData,
  oAddress,
  oWrEN
);

input iRstN,iRx, iClk, iMode;
output oWrEN;
output reg[63:0] oData;
output reg[18:0] oAddress;
output oBusy;

// ----------------- inner registers and wires ----------------------------
reg [2:0] state = 0;
reg prevReady = 1;
reg [18:0] addressCount = 0;
wire uartReady, uartWrE, uartEop, uartIdle;
wire [7:0] uartData;

// ------------------ assigns ---------------------------------------------
assign oWrEN = ~iMode;
assign oBusy = ~uartIdle;

// ------------------ always blocks ---------------------------------------
always@(posedge iClk or negedge iRstN)begin 
  if(!iRstN) begin
    addressCount <= 19'd0;
    state <= 3'b0;  
  end
  else begin  
  if(iMode) begin
    prevReady <= uartReady;
    if({prevReady,uartReady} == 2'b01) begin
      state <= 3'b0;
      oAddress <= addressCount;
      oData <= {56'd0, uartData};
      addressCount <= addressCount + 1'd1;
    end
  end
  else begin
    if(uartEop) state <= 3'd0;
    else begin
      prevReady <= uartReady;
      if({prevReady,uartReady} == 2'b01) begin
        case(state)
          0: oData[ 7: 0] <= uartData;
          1: oData[15: 8] <= uartData;
          2: oData[23:16] <= uartData;
          3: oData[31:24] <= uartData;
          4: oData[39:32] <= uartData;
          5: oData[47:40] <= uartData;
          6: oData[55:48] <= uartData;
          7: oData[63:56] <= uartData;
        endcase
        state <= state + 1'b1;
        end
      end
    end
  end
end

// ---------------- sub-modules ------------------------------------------
AsyncReceiver rec(
  .iClk(iClk), 
  .iRx(iRx), 
  .oRxReady(uartReady), 
  .oRxData(uartData),
  .oRxEop(uartEop), 
  .oRxIdle(uartIdle)
);

endmodule
